<?php

namespace app\common\model;

use app\common\BaseModel;
use Exception;
use think\db\exception\DbException;

class Order extends BaseModel
{
    const CREATE_ORDER = 1;//创建订单
    const ORDER_SUCCEED = 2;//订单支付成功
    const ORDER_FAILED = 3;//订单支付失败

    const NO_PAYMENT_STATE = 0;//未支付成功
    const WAIT_STATE = 1;//待处理
    const FINISH_STATE = 2;//已处理
    const FAILED_STATE = 3;//处理失败

    public static $fieldTypes = [
        'id' => 'number',
        'account' => 'string',
        'goods_name' => 'string',
        'order_num' => 'string',
        'transaction_id' => 'string',
        'owner_address' => 'string',
        'status' => 'number',
        'state' => 'number',
        'payment_type' => 'number',
        'created_at' => 'date',
        'payment_time' => 'date',
    ];

    /**
     * 创建订单
     * @param $data
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function createOrder($data)
    {
        $insertData = [
            'goods_name' => base64_encode($data['goods_name']),
            'goods_price' => $data['goods_price'] * 100,
            'goods_amount' => $data['goods_amount'],
            'account' => $data['account'],
            'payment_type' => $data['payment_type'],
            'order_num' => self::buildOrderNum(),
            'payment_price' => self::buildPaymentPrice($data['goods_price'], $data['goods_amount']),
            'state' => self::NO_PAYMENT_STATE,
            'status' => self::CREATE_ORDER,
            'is_deleted' => self::NO_DELETED,
            'created_at' => date('Y-m-d H:i:s')
        ];

        $insertData['id'] = self::insertGetId($insertData);

        return $insertData;
    }

    /**
     * 保存数据
     * @param $data
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws Exception
     * @throws ModelNotFoundException
     */
    public static function saveData($data)
    {
        if(!$modelRecord = self::findById($data['id'])) {
            throw new Exception('该订单不存在');
        }

        if($modelRecord->status != self::ORDER_SUCCEED) {
            throw new Exception('该笔订单未支付成功,不能处理');
        }

        if(!in_array($modelRecord->state, [1, 3])) {
            throw new Exception('仅支持待处理或处理失败的订单');
        }

        $modelRecord->state = self::FINISH_STATE;
        if(isset($data['remark'])) $modelRecord->remark = $data['remark'];

        $modelRecord->save();
    }

    /**
     * 查询订单
     * @param $orderNum
     * @return Order|array|mixed|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function findByOrderNum($orderNum)
    {
        return  self::findNoDeleted(['order_num' => $orderNum]);
    }

    /**
     * 查询支付成功的订单
     * @param $orderNum
     * @return Order|array|mixed|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function findOrderPaymentSuccess($orderNum)
    {
        return self::findNoDeleted(['order_num' => $orderNum, 'status' => self::ORDER_SUCCEED]);
    }

    /**
     * 构建支付价格
     * @param $goodsPrice
     * @param int $goodsAmount
     * @return false|float
     */
    public static function buildPaymentPrice($goodsPrice, $goodsAmount = 1)
    {
        $price = strval($goodsPrice * $goodsAmount);

        if(false === stripos($price, '.')) {
            $bit = 2;
        }else{
            $numExp = explode('.', strval($price));
            $descLen = strlen($numExp[1]);
            $bit = max($descLen, 2);
        }

        $randDesc = mt_rand(100000, 999999) / 1000000 / pow(10, $bit);
        $retPrice = round(($price + $randDesc), 6);
        $retPrice = sprintf("%.6f", $retPrice);

        return $retPrice;
    }

    /**
     * 构建订单号
     * @param string $prefix
     * @return string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function buildOrderNum($prefix = 'trc20')
    {
        $str = $prefix . date("YmdHis") . uniqid() . time() . sha1(hrtime(true)) . mt_rand(100000, 999999);
        $orderNum = strtoupper(md5(str_shuffle($str)));

        do{
            $orderActive = self::findByOrderNum($orderNum);
        }while($orderActive);

        return $orderNum;
    }
}